<?php
class Agitum_Controller_Action_CRUD extends Agitum_Controller_Action
{
	protected $object = null;
	
	const ACTION_READ  = 'index';
    const ACTION_VIEW   = 'view';
    const ACTION_CREATE = 'create';
    const ACTION_UPDATE   = 'edit';
    const ACTION_DELETE = 'delete';
    const ACTION_COMPLETE = 'complete';
    
    const BUTTON_SAVE       = 'save';
    const BUTTON_SAVEEDIT   = 'saveedit';
    const BUTTON_SAVECREATE = 'savecreate';
    
    protected $buttonLabels    = array(
        self::BUTTON_SAVE       => 'Save',
        self::BUTTON_SAVEEDIT   => 'Save and continue editing',
        self::BUTTON_SAVECREATE => 'Save and create new one'
    );
    
    protected $messageTemplates = array(
        self::ACTION_CREATE => 'New %s has been created.',
        self::ACTION_UPDATE => 'The %s has been updated.',
        self::ACTION_DELETE => 'The %s has been deleted.',
    );
    
    protected $options = array(
        'pkEditable'        => false,
        'viewFolder'        => 'crud',
        'entityTitle'       => 'entity',
        'readonly'          => false,
        'disabledActions'   => array(),
        'createButtons'     => array(
            self::BUTTON_SAVE,
            self::BUTTON_SAVEEDIT,
            self::BUTTON_SAVECREATE
        ),
        'routes'            => array()
    );
    
    protected $fields;
    protected $db;
    protected $meta;
    
    protected $_redirector;
    
	public function init() {
		$this->_redirector = $this->_helper->getHelper('Redirector');
	}
	
	public function initCRUD($class, $fields = array(), $options = null ) 
	{
		if ( is_string($class) ) {
			$class = new $class();
		} 
		if ( is_object($class) ) {
			if ( ! $class instanceof Agitum_Model_Object )
				throw new Exception('CRUD require instace of Agitum_Model_Object as data provider');
		} else {
			throw new Exception('CRUD require class name or instace of Agitum_Model_Object as data provider');
		}
		
		if (isset($options['readonly']) && $options['readonly']) {
			$this->options['disabledActions'] = array(self::ACTION_CREATE, self::ACTION_DELETE, self::ACTION_UPDATE);
		}
		
		$this->object = $class;
		
		$this->db     = Zend_Registry::get('Zend_Db');
        $this->fields = $fields;
        if (is_array($options)) {
            $this->options = array_merge($this->options, $options);
        }
        
        $action         = $this->getRequest()->getActionName();
        $crudActions   = array(self::ACTION_VIEW, self::ACTION_READ,
                              self::ACTION_CREATE, self::ACTION_UPDATE,
                              self::ACTION_DELETE, self::ACTION_COMPLETE);
                              
        if (in_array($action, $crudActions)) {
            $this->getHelper('ViewRenderer')
                 ->setViewScriptPathSpec(sprintf('%s/:action.:suffix', $this->options['viewFolder']));
        }
        
        $this->action = $this->getRequest()->getActionName();
        $this->module = $this->getRequest()->getModuleName();
		$this->controller = $this->getRequest()->getControllerName();
		
		$this->view->acl = Zend_Registry::get('Zend_Acl');
		
		$route = new stdClass();
		$route->module     = $this->module;
        $route->controller = $this->controller;
        $route->action = $this->action;
        
        $front = Zend_Controller_Front::getInstance();
		$router = $front->getRouter();
		
        $route->current = $router->getCurrentRouteName();
        
        if ( count($this->options['routes']) ) 
        {
            $route->index = $this->options['routes']['index'];
            $route->create = $this->options['routes']['create'];
            $route->view = $this->options['routes']['view'];
            $route->edit = $this->options['routes']['edit'];
            $route->delete = $this->options['routes']['delete'];
        } 
        else 
        {
    		$route->edit = sprintf('%s_%s_edit', $this->module, $this->controller);
    		$route->create = sprintf('%s_%s_create', $this->module, $this->controller);
    		$route->delete = sprintf('%s_%s_delete', $this->module, $this->controller);
        }
		
        $this->view->route = $route;
        //$this->view->messages   = $this->_helper->getHelper('FlashMessenger')->getMessages();
	}
	
	public function postDispatch()
    {
//    	$controller = $this->getRequest()->getControllerName();
//    	$this->getHelper('ViewRenderer')->setViewScriptPathSpec(':controller/:action.:suffix');
    }
	
	public function indexAction() 
	{
		$front = Zend_Controller_Front::getInstance();
		$router = $front->getRouter();
		$this->view->current_route_name = $router->getCurrentRouteName();
		$this->view->is_tree = false;
		
		if ( $this->object instanceof Agitum_Model_Tree) {
			$this->view->data = $this->object->getTree();
			$this->view->is_tree = true;
		} else {
			$this->view->data = $this->object->fetchAll();
		}
	}
	
	public function createAction() 
	{
		$this->view->form = $this->_prepareForm();
	    if ( $this->_request->isPost() ) {
			$params = $this->_request->getPost();
			if ( $this->view->form->isValid($params) ) {
			    unset($params['id']);
				foreach ( $this->object as $key => $val ) {
					if ( isset($params[$key]) ) {
						$this->object->$key = $params[$key];
					}
				}
				$this->object->save();
				$this->_redirector->gotoUrl(sprintf('/%s/%s',$this->view->module, self::ACTION_LIST) );
			}
		}
	}
	
	public function editAction() 
	{
		$id = $this->_request->getParam('id', null);
		if ( !$id ) {
			$this->_redirector->gotoUrl(sprintf('/%s/%s',$this->view->module, $this->view->controller) );
		}
		$this->object->id = $id;
		$this->object->find();
		$this->view->data = $this->object;
		$this->view->form = $this->_prepareForm();
		if ( $this->_request->isPost() ) {
			$params = $this->_request->getPost();
			if ( $this->view->form->isValid($params) ) {
				foreach ( $this->object as $key => $val ) {
					if ( isset($params[$key]) ) {
						$this->object->$key = $params[$key];
					}
				}
				$this->object->save();
				$this->_redirector->gotoUrl(sprintf('/%s/%s',$this->view->module, self::ACTION_LIST) );
			}
		}
	}
	
	protected function _prepareForm() 
	{
		$form = new Zend_Form();
		$form->setMethod('post');
		
		$fields = $this->object->getFields();
		$types = array();
		
		foreach ( $fields as $key => $info ) {
			$class = isset($info['class']) ? $info['class'] : $info['DATA_TYPE'];
			$types[] = $info['DATA_TYPE'];
			switch(strtolower($info['DATA_TYPE'])) {
				case 'varchar':
					$item = new Zend_Form_Element_Text($key, array('class'=>$class));
					break;
				case 'int4': 
					$item = new Zend_Form_Element_Text($key, array('class'=>$class));
					break;
				case 'timestamp':
					$item = new Zend_Form_Element_Text($key, array('class'=>$class));
					break;
				case 'ltree':
					$item = new Zend_Form_Element_Text($key, array('class'=>$class));
					break;
				case 'bool':
					$item = new Zend_Form_Element_Checkbox($key, array('class'=>$class));
					break;
				case 'password':
					$item = new Zend_Form_Element_Password($key, array('class'=>$class));
					break;
				case 'hidden':
					$item = new Zend_Form_Element_Hidden($key, array('class'=>$class));
					break;
				case 'reference':
					$item = new Agitum_Form_Element_Reference($key, array('class'=>$class));
					break;
				default:
					$item = new Zend_Form_Element_Text($key, array('class'=>'unimplemented'));
					break;
			}
			if ( !$item ) continue;
			if ( !$item instanceof Zend_Form_Element_Hidden ) {
				$item->setLabel(isset($info['label']) ? $info['label'] : $key);
			}
			$item->setValue($this->object->$key);
			if ( isset($info['readOnly']) && $info['readOnly'] ) {
				$item->setAttrib('readonly', true);	
			}
			$form->addElement($item);
			
			$decors = array('ViewHelper', 'Errors', array(array('data' => 'HtmlTag'), array('tag' => 'div')) );
			if ( !$item instanceof Zend_Form_Element_Hidden ) {
				$decors[] = array(array('label' => 'Label'), array('tag' => 'div', 'escape' => false));
			}
			$decors[] = array(array('row' => 'HtmlTag'), array('tag' => 'div', 'id' => $item->getId().'-element', 'class' => $item->class ));
			
			$item->setDecorators($decors);
		}

		$sbmt = new Zend_Form_Element_Submit('submit');
		$sbmt->setLabel($this->buttonLabels[ self::BUTTON_SAVE ]);
		$form->addElement($sbmt);
		
		$sbmt->setDecorators(array('ViewHelper', array('data'=>'HtmlTag', 'tag'=>'div')));

        $form->setDecorators(array(
		    'FormElements',
		    array('HtmlTag', array('tag' => 'div', 'id' => $this->object->relname)),
		    'Form',
		));
		return $form;
	}
	
	public function validateAction()
	{
		$this->_helper->viewRenderer->setNoRender();
		$this->_helper->layout()->disableLayout();

		$form = $this->_prepareForm();
		$form->isValid($this->_request->getPost());
		$json = $form->getMessages();

//		$this->_response->setHeader('Content-Type', 'application/json');
		echo Zend_Json::encode($json);
	}
	
	public function completeAction() 
	{
		$this->_helper->viewRenderer->setNoRender();
		$this->_helper->layout()->disableLayout();

    	$term = $this->_request->getParam('query', null);
    	if ( !$term ) return;
    	
    	$level = null;
    	if ( $this->object instanceof Agitum_Model_Tree) {
    		$level = $this->_request->getParam('level', null);
    	}
    	
    	$rows = $this->object->search($term, $level);
		
		$data = array();
		$suggest = array();
		foreach ($rows as $i => $row) {
			$data[] = $row['id'];
			$suggest[] = $row['title'];
		}

//		$this->_response->setHeader('Content-Type', 'application/json');
		echo Zend_Json::encode(array('query' => $term, 'suggestions' => $suggest, 'data' => $data ));
	}
	
	public function createbtnAction() {}
}